#include "SceneLoader.h"

#include <osgDB/ReadFile>
#include <amk3/EarthWrapper.h>
#include <osgDB/FileUtils>

#include <osg/Material>
#include <math.h>
#include "InsConfig.h"
#include <amk3/FileUtil.h>
#include <osgGA/TrackballManipulator>
#include <QString>
#include "Services/ScenePointCloud.h"
#include "Services/SceneInstanceBuilding.h"


void _processNode(osg::Node* pn, int intcolor) {
	osg::Group* group = pn->asGroup();
	if (!group || group->getNumChildren() < 1)
	{
		return;
	}

	osg::Geometry* geom = 0;

	osg::Geode* geode = group->getChild(0)->asGeode();
	if (geode && geode->getNumDrawables() > 0)
	{
		geom = geode->getDrawable(0)->asGeometry();
	}
	if (!geom)
	{
		geom = group->getChild(0)->asGeometry();
	}
	if (!geom)
	{
		return;
	}

	//iidd = 0b110000011100000001;
	int b = (intcolor >> 16) % 256;
	int g = (intcolor >> 8) % 256;
	int r = intcolor % 256;
	//osg::Geometry* geom =  geode->getDrawable(0)->asGeometry();
	osg::StateSet* pss = geom->getOrCreateStateSet();
	osg::Material* mat = new osg::Material();
	mat->setColorMode(osg::Material::ColorMode::EMISSION);
	mat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(0.0, 0.0, 0.0, 1));
	mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(0.0, 0.0, 0.0, 1));
	mat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(0.0, 0.0, 0.0, 1));
	mat->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4((float)r / 255.0, (float)g / 255.0, (float)b / 255.0, 1.0f));
	pss->setAttribute(mat, osg::StateAttribute::ON);
	//pss->setTextureAttributeAndModes(0, osg::StateAttribute::ON);
	pss->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
	pss->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::OFF);
}


int SceneLoader::loadScene()
{
	if (InsConfig::instance()->scene_type == "OSGEARTH")
	{
		std::string path = InsConfig::instance()->scene_path;
		EarthWrapper::instance()->createMapNode(path);
	}
	else if (InsConfig::instance()->scene_type == "OSGB")
	{
		std::string path = InsConfig::instance()->scene_path;

		osg::Node* pn = osgDB::readNodeFile(path);
		if (pn)
		{
			EarthWrapper::instance()->getRootNode()->addChild(pn);
			EarthWrapper::instance()->getViewer()->setCameraManipulator(new osgGA::TrackballManipulator());
		}

	}
	else if (InsConfig::instance()->scene_type == "OSGB_FILES")
	{
		std::string path = InsConfig::instance()->scene_path;
		std::string filter = InsConfig::instance()->scene_nameFilter;
		std::vector<std::string> files = FileUtil::searchFiles(path, filter);

		osg::Group* root = new osg::Group();
		for (int i = 0; i < files.size(); i += 30)
		{
			osg::Node* pn = osgDB::readNodeFile(files[i]);
			if (pn)
			{
				//_processNode(pn, files[i]);
				root->addChild(pn);
			}
		}
		EarthWrapper::instance()->getRootNode()->addChild(root);
		EarthWrapper::instance()->getViewer()->setCameraManipulator(new osgGA::TrackballManipulator());
	}
	else if (InsConfig::instance()->scene_type == "OSGB_FILES_NAMEMASK")
	{
		std::string path = InsConfig::instance()->scene_path;
		std::string filter = InsConfig::instance()->scene_nameFilter;
		std::vector<std::string> files = FileUtil::searchFiles(path, filter);

		osg::Group* root = new osg::Group();
		for (int i = 0; i < files.size(); i += 1)
		{
			osg::Node* pn = osgDB::readNodeFile(files[i]);
			if (pn)
			{
				std::string fname = files[i];
				int pos_1 = fname.find_last_of('/');
				int pos_2 = fname.find_last_of('.');
				std::string filename = fname.substr(pos_1 + 1, pos_2 - pos_1 - 1);
				int iidd = QString::fromStdString(filename).toInt();

				_processNode(pn, iidd);
				root->addChild(pn);
			}
		}
		EarthWrapper::instance()->getRootNode()->addChild(root);
		EarthWrapper::instance()->getViewer()->setCameraManipulator(new osgGA::TrackballManipulator());
	}
	else if (InsConfig::instance()->scene_type == "3DTILES_OSGB")
	{
		std::string path = InsConfig::instance()->scene_path;

		std::string dataPath = path + "/Data/";
		osgDB::DirectoryContents dirNames = osgDB::getDirectoryContents(dataPath);
		osgDB::DirectoryContents::iterator iter = dirNames.begin();
		osg::Group* root = new osg::Group();
		while (iter != dirNames.end()) {
			std::string dir = *iter;
			if (dir.find(".") != std::string::npos) {
				iter++;
				continue;
			}

			std::string osgbFile = dataPath + dir + "\\" + dir + ".osgb";
			osg::Node* c = osgDB::readNodeFile(osgbFile);
			root->addChild(c);
			iter++;

		}
		EarthWrapper::instance()->getRootNode()->addChild(root);
		auto bd = root->getBound();
		EarthWrapper::instance()->getViewer()->setCameraManipulator(new osgGA::TrackballManipulator());
	}
	else if (InsConfig::instance()->scene_type == "POINTCLOUD")
	{
		std::string path = InsConfig::instance()->scene_path;
		ScenePointCloud spc;
		osg::Node* pn = spc.getNode(path, InsConfig::instance());
		if (!pn)
		{
			return -1;
		}
		EarthWrapper::instance()->getRootNode()->addChild(pn);
		EarthWrapper::instance()->getViewer()->setCameraManipulator(new osgGA::TrackballManipulator());
	}
	else if (InsConfig::instance()->scene_type == "3DTILES_OSGB_MASK")
	{
		std::string path = InsConfig::instance()->scene_path;

		std::string dataPath = path + "/Data/";
		osgDB::DirectoryContents dirNames = osgDB::getDirectoryContents(dataPath);
		osgDB::DirectoryContents::iterator iter = dirNames.begin();
		osg::Group* root = new osg::Group();
		while (iter != dirNames.end()) {
			std::string dir = *iter;
			if (dir.find(".") != std::string::npos) {
				iter++;
				continue;
			}

			std::string osgbFile = dataPath + dir + "\\" + dir + ".osgb";
			osg::Node* c = osgDB::readNodeFile(osgbFile);
			if (c) {
				int iidd = QString::fromStdString(dir).toInt();
				_processNode(c, iidd);
				root->addChild(c);
			}
			
			iter++;

		}
		EarthWrapper::instance()->getRootNode()->addChild(root);
		EarthWrapper::instance()->getViewer()->setCameraManipulator(new osgGA::TrackballManipulator());
	}
	else if (InsConfig::instance()->scene_type == "InstanceBuilding")
	{
		std::string path = InsConfig::instance()->scene_path;
		SceneInstanceBuilding spc;
		osg::Node* pn = spc.getNode(path, InsConfig::instance());
		if (!pn)
		{
			return -1;
		}
		EarthWrapper::instance()->getRootNode()->addChild(pn);
		EarthWrapper::instance()->getViewer()->setCameraManipulator(new osgGA::TrackballManipulator());
	}
	return  0;
}
